﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using PaperRenderingInterfaces;
using DeepZoomPivotConstructor.PivotLib;
using HtmlAgilityPack;
using PaperPluginUtilities;
using RenderEngineInterfaces;
using DeepZoomPivotConstructor.VisualLib;
using System.Text.RegularExpressions;

namespace CMSPages
{
    /// <summary>
    /// Can the CMS event display web pages and grab all the evnet displays we can! :-)
    /// </summary>
    [Export(typeof(IPaperRender))]
    [PaperRender("CMSEventDisplayPage")]
    public class ScanCMSEventDisplayPages : IPaperRender
    {
        /// <summary>
        /// Get our web data!
        /// </summary>
        [Import]
        IWebAccess WebGetter;

        /// <summary>
        /// For creating the visual hierarchy
        /// </summary>
        [Import]
        IRenderEngine MyRender;

        /// <summary>
        /// Scan the given address as a page of CMS event displays
        /// </summary>
        /// <param name="renderAddress"></param>
        /// <returns></returns>
        public IEnumerable<PivotImage> Render(string renderAddress)
        {
            ///
            /// Fetch the web data
            ///

            Uri masterUri = new Uri(renderAddress);
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(WebGetter.GetUriAsString(masterUri));

            ///
            /// Now, scan for the proper stuff and start returning it! :-)
            /// 

            var allGoodInfo = doc.DocumentNode.ScanSubNodes(n => n.Name == "a" || n.Name == "#text");

            string lastDescription = "";
            var extractedDescription = allGoodInfo.Apply(n => {
                string inner = n.InnerText.CleanHTMLText();
                if (n.Name == "#text" && IsGoodDescript(inner)) {
                    lastDescription = inner;
                }
            });

            var allLinks = from l in extractedDescription where l.Name == "a" select l;
            var eventDisplayImages = from lnk in allLinks
                                     let href = lnk.Attributes["href"].Value
                                     where href != null && lnk.ContainsTag("img")
                                     let imgUri = new Uri(masterUri, href)
                                     select new {
                                         TheUri = imgUri,
                                         Text = lastDescription
                                     };

            return eventDisplayImages.Select(u => ConvertEDToPI(u.TheUri, u.Text, masterUri));
        }

        /// <summary>
        /// Look at the description - is it good enough to adopt!? :-)
        /// </summary>
        /// <param name="inner"></param>
        /// <returns></returns>
        private bool IsGoodDescript(string inner)
        {
            if (inner == null || inner.Length == 0)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// Returns a pivot image of the event display guy we've been handed.
        /// </summary>
        /// <param name="u"></param>
        /// <returns></returns>
        private PivotImage ConvertEDToPI(Uri u, string descrip, Uri baseUri)
        {
            ///
            /// Get the visual we are going to digitize here
            /// 

            Visual v = MyRender.Render(u, forceAsComposableUnit: true);

            PivotImage p = new PivotImage(v);

            ///
            /// Now, fill in all the info!
            /// 

            p.Name = ExtractNameFromFile(u.Segments.Last());
            p.Description = descrip;

            p.Add("Note Title", "CMS Event Displays");
            p.Add("More Informaion", "Web Page", baseUri);
            p.Add("Caption", descrip);
            p.Add("Graphics Files", u.GetNormalizedFileExtension(), u);
            var dt = WebGetter.GetLastModificationTime(u);
            if (dt.HasValue)
            {
                p.Add("Date", dt.Value);
            }

            return p;
        }

        private Regex RunEvtScanner = new Regex(".+r([0-9]+)[^0-9]*e([0-9]+)[^0-9].+");

        /// <summary>
        /// Try to get run/event number out of this guy
        /// Some examples of what we can deal with:
        /// fws_r132440_e2731900.jpg
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private string ExtractNameFromFile(string p)
        {
            var m = RunEvtScanner.Match(p);
            if (m == null || !m.Success)
            {
                return "Run and Event not matched";
            }

            string run = m.Groups[1].Value;
            string evt = m.Groups[2].Value;

            return "CMS Run " + run + " Event " + evt;
        }
    }
}
